/*
 * Copyright (c) 2010-present www.walkerljl.org All Rights Reserved.
 * The software source code all copyright belongs to the author, 
 * without permission shall not be any reproduction and transmission.
 */
package org.walkerljl.commons.security;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.walkerljl.commons.Constants;
import org.walkerljl.commons.exception.UncheckedException;

/**
 * EncryptUtils
 * @author lijunlin
 */
public class EncryptUtils {
	
    public static String encodeURI(String str) {
        try {
            return URLEncoder.encode(str, "UTF-8");
        } catch (Exception e) {
            return str;
        }
    }
    
    public static String decodeURI(String str) {
        try {
            return URLDecoder.decode(str, "UTF-8");
        } catch (Exception e) {
            return str;
        }
    }
	
	/**
	 * 使用MD5加密
	 * @param data
	 * @return
	 */
	public static String encryptByMD5(String data) {
		if (null == data || "".equals(data)) 
			return "";
		MessageDigest md5 = null;
		try {
			// 获得MD5摘要算法的 MessageDigest 对象
			md5 = MessageDigest.getInstance("MD5");
		} 
		catch (NoSuchAlgorithmException exception) {
			return "";
		}
		// 将传入字符串转换为字符数组
		char[] chars = data.toCharArray();
		byte[] bytes = new byte[chars.length];
		// 将字符数组转化为字节数组
		for (int i = 0; i < chars.length; i++) {
			bytes[i] = (byte) chars[i];
		}
		// 使用指定的字节更新摘要，并获得密文
		byte[] md5Bytes = md5.digest(bytes);
		StringBuilder result = new StringBuilder();
		// 把密文转换成十六进制的字符串形式
		for (int i = 0; i < md5Bytes.length; i++) {
			int val = ((int) md5Bytes[i]) & 0xff;
			if (16 > val) {
				result.append("0");
			}
			result.append(Integer.toHexString(val));
		}
		return result.substring(8, 24);
	}
	
	 /**
     * 加密DES字符串
     * @param strIn
     * @return
     */
    public static String encryptByDES(String strIn) {
        try {
            Cipher cipher = getDesCipher("encrypt");
            return byteArr2HexStr(cipher.doFinal(strIn.getBytes()));
        } catch (Exception e) {
            throw new UncheckedException(e);
        }
    }

    /**
     * 解密DES字符串
     * @param strIn
     * @return
     * @throws Exception
     */
    public static String decryptByDES(String strIn) {
        try {
            Cipher cipher = getDesCipher("decode");
            return new String(cipher.doFinal(hexStr2ByteArr(strIn)));
        } catch (Exception e) {
        	throw new UncheckedException(e);
        }
    }

    private static Cipher getDesCipher(String type) {
        Cipher cipher = null;
        try {
            // 实例化DES密钥
            DESKeySpec dks = new DESKeySpec(Constants.DES_KEY.getBytes());
            // 实例化密钥工厂
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            // 生成密钥
            SecretKey secretKey = keyFactory.generateSecret(dks);
            cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");// 加密/解密/工作模式/填充方式
            if ("encrypt".equals(type)) {
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            } else {
                cipher.init(Cipher.DECRYPT_MODE, secretKey);
            }
        } catch (Exception e) {
        	throw new UncheckedException(e);
        }
        return cipher;
    }

    public static String byteArr2HexStr(byte[] arrB) throws Exception {
        int iLen = arrB.length;
        StringBuffer sb = new StringBuffer(iLen * 2);
        for (int i = 0; i < iLen; i++) {
            int intTmp = arrB[i];
            while (intTmp < 0) {
                intTmp = intTmp + 256;
            }
            if (intTmp < 16) {
                sb.append("0");
            }
            sb.append(Integer.toString(intTmp, 16).toUpperCase());
        }
        return sb.toString();
    }

    private static byte[] hexStr2ByteArr(String strIn) throws Exception {
        byte[] arrB = strIn.getBytes();
        int iLen = arrB.length;

        // 两个字符表示一个字节，所以字节数组长度是字符串长度除以2
        byte[] arrOut = new byte[iLen / 2];
        for (int i = 0; i < iLen; i = i + 2) {
            String strTmp = new String(arrB, i, 2);
            arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
        }
        return arrOut;
    }
	
	public static void main(String[] args) {
		System.out.println(encryptByMD5("jarvis00"));
	}
}